/**********************************************************************
 * Filename: Jogo.java
 * Created: 2012/04/23
 * @author Fernando Brito e Abreu
 **********************************************************************/
package iscte.es.copaPaises.businessLayer;


import java.util.LinkedList;
import java.util.Set;
import java.util.HashSet;
import java.util.SortedSet;


public class Jogo
{
	public static Set<Jogo> allInstances = new HashSet<Jogo>();

	private CalendarDate dia;
	private String hora;
	private Grupo grupo;
	private Estadio estadio;

	/**********************************************************************
	 * Default constructor
	 **********************************************************************/
	public Jogo()
	{
		allInstances.add(this);
	}

	/**********************************************************************
	 * Parameterized constructor
	 * @param dia the dia to initialize
	 * @param hora the hora to initialize
	 * @param grupo the grupo to initialize
	 * @param estadio the estadio to initialize
	 **********************************************************************/
	public Jogo(CalendarDate dia, String hora, Grupo grupo, Estadio estadio)
	{
		this.dia = dia;
		this.hora = hora;
		this.grupo = grupo;
		this.estadio = estadio;
		allInstances.add(this);
	}

	/**********************************************************************
	 * Standard attribute getter
	 * @return the dia of the jogo
	 **********************************************************************/
	public CalendarDate dia()
	{
		return dia;
	}

	/**********************************************************************
	 * Standard attribute setter
	 * @param dia the dia to set
	 **********************************************************************/
	public void setDia(CalendarDate dia)
	{
		this.dia = dia;
	}

	/**********************************************************************
	 * Standard attribute getter
	 * @return the hora of the jogo
	 **********************************************************************/
	public String hora()
	{
		return hora;
	}

	/**********************************************************************
	 * Standard attribute setter
	 * @param hora the hora to set
	 **********************************************************************/
	public void setHora(String hora)
	{
		this.hora = hora;
	}

	/**********************************************************************
	 * ONE2MANY getter for Jogo[*] <-> Grupo[1]
	 * @return the grupo of the jogo
	 **********************************************************************/
	public Grupo grupo()
	{
		return grupo;
	}

	/**********************************************************************
	 * ONE2MANY setter for Jogo[*] <-> Grupo[1]
	 * @param grupo the grupo to set
	 **********************************************************************/
	public void setGrupo(Grupo grupo)
	{
		this.grupo = grupo;
	}

	/**********************************************************************
	 * ONE2MANY getter for Jogo[*] <-> Estadio[1]
	 * @return the estadio of the jogo
	 **********************************************************************/
	public Estadio estadio()
	{
		return estadio;
	}

	/**********************************************************************
	 * ONE2MANY setter for Jogo[*] <-> Estadio[1]
	 * @param estadio the estadio to set
	 **********************************************************************/
	public void setEstadio(Estadio estadio)
	{
		this.estadio = estadio;
	}

	/**********************************************************************
	 * MEMBER2ASSOCIATIVE getter for Jogo[*] <-> Equipa[2] ordered
	 * @return the equipa of the jogo
	 **********************************************************************/
	public LinkedList<Equipa> equipa()
	{
		LinkedList<Equipa> result = new LinkedList<Equipa>();
		for (Equipa x : Equipa.allInstances){
			if (x.jogo()  ==  this){
				result.add(x);
			}
		}
		return result;
	}

	/**********************************************************************
	 * MEMBER2ASSOCIATIVE setter for Jogo[*] <-> Equipa[2] ordered
	 * @param equipa the equipa to set
	 **********************************************************************/
	public void setEquipa(SortedSet<Equipa> equipa)
	{
		for (Equipa x : equipa)
			x.setJogo(this);
	}

	/**********************************************************************
	 * MEMBER2MEMBER getter for Jogo[*] <-> Pais[2] ordered
	 * @return the seleccao of the jogo
	 **********************************************************************/
	public LinkedList<Pais> seleccao()
	{
		LinkedList<Pais> result = new LinkedList<Pais>();	
		
		for (Equipa x : Equipa.allInstances){
			if (x.jogo()  ==  this){
				result.add(x.seleccao());
			}
		}
		return result;

	}

	/**********************************************************************
	 * MEMBER2MEMBER setter for Jogo[*] <-> Pais[2] ordered
	 * @param seleccao the seleccao to set
	 **********************************************************************/
	public void setSeleccao(SortedSet<Pais> seleccao)
	{
		boolean encontrado;
		for (Pais t : seleccao){
			encontrado=false;
			for (Equipa x: Equipa.allInstances){
				if (x.jogo() == this && x.seleccao()==null &&encontrado==false){
					x.setSeleccao(t);
					encontrado=true;
				}
			}
		}
	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * @param data the data to set
	 * @param hora the hora to set
	 * @param visitado the visitado to set
	 * @param visitante the visitante to set
	 * @param estadio the estadio to set
	 * @param grupo the grupo to set
	 **********************************************************************/
	public void inicializa(String data, String hora, Pais visitado, Pais visitante, Estadio estadio, Grupo grupo)
	{
		//	DONE
		//	dummy := new CalendarDate;
		//	 self.dia := dummy.stringToDate(data);
		//	 destroy dummy;
		//	 self.hora := hora;

		//	 if visitado.isDefined then new Equipa between (visitado,self) end;
		//	 if visitante.isDefined then new Equipa between (visitante,self) end;

		//	 insert (estadio,self) into Estadio_Jogo;
		//	 insert (grupo,self) into Grupo_Jogo;

		CalendarDate dummy = new CalendarDate();
		this.dia = dummy.stringToDate(data);
		dummy.destroy();
		this.hora = hora;
		this.grupo = grupo;
		this.estadio = estadio;

		for(Pais p:Pais.allInstances){
			if(p.equals(visitado)){
				new Equipa(this,visitado);
			}
		}

		for(Pais p:Pais.allInstances){
			if(p.equals(visitante)){
				new Equipa(this,visitante);
			}
		}



	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 * @param hour the hour to set
	 **********************************************************************/
	public Float stringToHours()
	{
		//	DONE


		if(this.hora.length()==11){
			return    Integer.parseInt(this.hora.substring(0,2)) + Float.parseFloat(this.hora.substring(3,5))/60+ Integer.parseInt(this.hora.substring(10,11));
		}else{
			return    Integer.parseInt(this.hora.substring(0,1)) + Float.parseFloat(this.hora.substring(2,4))/60+ Integer.parseInt(this.hora.substring(9,10));
		}
		//return ((hour.substring(1,2).toInteger + (hour.substring(4,5).toInteger / 60)) + hour.substring(11,11).toInteger)

	}

	/**********************************************************************
	 * User-defined operation specified in SOIL/OCL
	 **********************************************************************/
	public String vencedor()
	{
		//	DONE
		int golos_e1=0;
		int golos_e2=0;

		for(Equipa eq:this.equipa()){
			if(eq.seleccao()==this.seleccao().getFirst()){
				for(Membro m:eq.membro()){
					golos_e1+=m.golos().size();
				}
			}
			if(eq.seleccao()==this.seleccao().getLast()){
				for(Membro m:eq.membro()){
					golos_e2+=m.golos().size();
				}
			}
		}

		if(golos_e1>golos_e2){
			return this.seleccao().getFirst().nome();
		}else{
			if(golos_e1<golos_e2){
				return this.seleccao().getLast().nome();
			}else{
				return "Empate";
			}
		}

		//	return if (self.equipa->collectNested($e : Equipa | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->select($elem1 : Golo | ($elem1.marcador.jogador.nacionalidade = self.seleccao->first))->size > self.equipa->collectNested($e : Equipa | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->select($elem2 : Golo | ($elem2.marcador.jogador.nacionalidade = self.seleccao->last))->size) then self.seleccao->first.nome else if (self.equipa->collectNested($e : Equipa | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->select($elem3 : Golo | ($elem3.marcador.jogador.nacionalidade = self.seleccao->first))->size < self.equipa->collectNested($e : Equipa | $e.membro)->flatten->collectNested($e : Membro | $e.golos)->flatten->select($elem4 : Golo | ($elem4.marcador.jogador.nacionalidade = self.seleccao->last))->size) then self.seleccao->last.nome else 'empate' endif endif
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	/**********************************************************************
	 * Object serializer
	 **********************************************************************/
	public String toString()
	{
		return "Jogo [dia=" + dia + ", hora=" + hora + ", grupo=" + grupo + ", estadio=" + estadio + "]\n";
	}

	//	-------------------------------------------------------------------------------
	//	INVARIANTS (TODO)
	/*
	inv HorasDosJogos
		((self.hora.substring(1,2).toReal < 23) and (self.hora.substring(1,2).toReal > 8))

	inv DatasDosJogos
		Jogo.allInstances->collectNested($e : Jogo | $e.grupo)->select($elem15 : Grupo | ($elem15.fase = FaseCampeonato::MeiasFinais))->collectNested($e : Grupo | $e.jogos)->flatten->forAll(j : Jogo | Jogo.allInstances->collectNested($e : Jogo | $e.grupo)->select($elem16 : Grupo | ($elem16.fase = FaseCampeonato::Final))->collectNested($e : Grupo | $e.jogos)->flatten->forAll(h : Jogo | j.dia.isBefore(h.dia)))

	 */

}
